Upskill tutorial for (avoiding) inheritance

Hud Wahab
4 min readJul 13, 2023

--

Day 13: Dotenv. Property.

Hi 👋 I am Hud, a postdoc for engineering data science at the AI Manufacturing Center in Laramie, Wyoming. My funding is running out (AaAaaA !), so while I am actively looking for a new job, instead of doing the 205th coding certificate to prove my worthiness — I thought I’d do design challenges and document how I spend my time upskilling so other engineers can do the same.

Nowadays, certificates are everywhere. Documenting small upskill projects that you can later show off is the best way to get recognition as a professional engineer.

This is day 13 of a 30-day design challenge. Follow along and let me know if you get stuck!

TL;DR tasks

Download the provided code for the challenge.

Task 1: Analyze the code and identify inheritance usage

  • Review the provided code and understand how inheritance is currently being used.
  • Identify the classes and their relationships to determine where inheritance is employed.

Task 2: Identify decoupling opportunities

  • Identify areas where inheritance can be replaced with other decoupling techniques, such as composition or interface implementation.
  • Consider the responsibilities and behavior of each class and how they can be separated effectively.

Task 3: Refactor the code to remove inheritance

  • Create a new design that eliminates the inheritance relationships in the code.
  • Replace the inheritance usage with appropriate alternatives, such as composition or interface implementation.
  • Modify the code structure to adhere to the new design.

Task 4: Test the refactored code

  • Verify that the refactored code functions correctly by running it with test cases or sample data.
  • Compare the output and behavior of the refactored code with the original version to ensure they are equivalent.

Task 5: Evaluate the improvements

  • Compare the refactored code with the original version and assess the benefits of removing the inheritance relationships.
  • Consider aspects such as code organization, maintainability, reusability, and flexibility.
  • Document the advantages gained and any other changes made in the refactored code.

Task 6: Document the refactor

  • Add comments or documentation to explain the changes made and the reasons behind them.
  • Describe the new design and how it improves the codebase compared to the original version.
  • Document any additional considerations or modifications made during the refactoring process.

The mess

The MyWeatherService class is inheriting from the WeatherService class, but it is not using any of the functionality provided by the parent class. Instead, it is simply calling the parent class's constructor and passing in some arguments. This is not a good use of inheritance, as it is not taking advantage of the parent class's functionality. It would be better to simply create a new class that does not inherit from WeatherService and instead just uses an instance of it. This would make the code more clear and easier to understand.

Additionally, we see inheritance is used to call the retrieve_forecast method of the parent class WeatherService. However, it is not really utilizing the functionality provided by the parent class. Instead, it is simply printing the temperature in Celsius. This could have been done without using inheritance, by simply creating a new method in the MyWeatherService class that prints the temperature.

Once we’ve downloaded the API key from here (it took an hour or two for it to work for me), and we run the code — we’d see something like this

The current temperature in Laramie is 19.5 °C.

Quite nice weather — why I am indoors writing this blog is a question I ask myself everyday.

The solution

We’ve given up on inheritance. We create a new instance of the WeatherService class that calls its retrieve_forecast method to get the weather data for a given city. It then uses the temperature property of the WeatherService instance to get the temperature in Celsius. This is a better design than using inheritance, as it separates the concerns of retrieving weather data and displaying the temperature. It also makes the code more flexible, as it can easily be modified to retrieve weather data for multiple cities.

Additionally, API key is nicely separated above in the code. An even better option would be to save this in a .env file outside of the code, which is a better practice for security or when sharing code.

We’ve also made temperature a property such that it can be accessed like an attribute of the WeatherService class, rather than as a method call.

The solution here is pretty simple and straightforward. But don’t worry, we’ll build up on this problem in the next challenge. Here’s what the new solution gets us:

The current temperature in Laramie is 24.5 °C.

Wow, see what happens when we don’t use inheritance— even better weather. On that note, I’ll take a break and be outside now.

Conclusion

Congratulations! You finished Day 13 from the 30-day design challenge.

If you have reached this far, you know how to:

  • Not use inheritance just for the sake of it
  • Not hardcode credentials in the code

Check out the day 14 challenge

Also, you can access the full 30-day GitHub repository here.

💡 My goal here is to help engineering data scientists upskill in design. I’d like to hear from you! Was this helpful? Anything I can improve? Connect with me on LinkedIn | Medium

--

--

Hud Wahab

🤖 Senior ML Engineer | Helping machine learning engineers design and productionize ML systems. | Let's connect: https://rb.gy/vb6au